package com.roger.springGreenwich.gateway.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.roger.springGreenwich.gateway.exception.NoTokenException;
import com.roger.springGreenwich.gateway.exception.TokenException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class MonoUtil {

    @Autowired
    private RedisUtil redisUtil;

    private static RedisUtil redisUtilService;

    @PostConstruct
    public void init(){
        redisUtilService = redisUtil;
    }

    private static final String AUTHORIZATION = "Authorization";

    private static final String CODE = "code";

    private static final String MSG = "msg";

    public static Mono<Void> buildReturnMono(ServerWebExchange exchange , GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        //指定编码，否则在浏览器中会中文乱码
        response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
        response.setStatusCode(HttpStatus.UNAUTHORIZED);

        HttpHeaders headers = request.getHeaders();
        String token = headers.getFirst(AUTHORIZATION);

        JSONObject json = new JSONObject();
        byte[] bits;
        DataBuffer buffer;
        DecodedJWT decodedJWT;
        try {
            if(StringUtils.isBlank(token) || !token.startsWith("Bearer:")){
                json.put(CODE, HttpStatus.UNAUTHORIZED.value());
                json.put(MSG, "没有token或token格式不正确");

                throw new TokenException("没有token或token格式不正确");
            }

            //verify black list
//            boolean hasBlackList = redisUtilService.hasKey(token.substring(7));
//            if(hasBlackList){
//                json.put(CODE, HttpStatus.UNAUTHORIZED.value());
//                json.put(MSG, "token已经过时");
//
//                throw new TokenException("token已经过时");
//            }

            //验证token是否超时
            decodedJWT = JWTUtils.verify(token.substring(7));
            if(decodedJWT == null){
                //log.error("token超时");
                json.put(CODE, HttpStatus.FORBIDDEN.value());
                json.put(MSG, "token超时");

                throw new TokenException("token超时");
            }

        } catch (TokenException e){
            json.toJSONString().getBytes(StandardCharsets.UTF_8);
            bits = json.toJSONString().getBytes(StandardCharsets.UTF_8);
            buffer = exchange.getResponse().bufferFactory().wrap(bits);
            response.bufferFactory().wrap(bits);
            response.writeWith(Flux.just(buffer));

            return response.writeWith(Flux.just(buffer));
        }catch (Exception e){
            response.setStatusCode(HttpStatus.GATEWAY_TIMEOUT);
            return response.setComplete();
        }


        //将用户信息通过头文件路由到微服务中
        try {
            Map<String , Object> hp = new HashMap();
            hp.put("username", decodedJWT.getClaim("username").asString());
            hp.put("id", decodedJWT.getClaim("id").asLong());
            hp.put("roles",decodedJWT.getClaim("roles").asString());

            String text = JSON.toJSONString(hp, SerializerFeature.WriteMapNullValue,SerializerFeature.WriteNullStringAsEmpty);
            String requestHeader = URLEncoder.encode(text,StandardCharsets.UTF_8.toString());

            ServerHttpRequest host = exchange.getRequest().mutate().header("loginUser", requestHeader).build();
            ServerWebExchange build = exchange.mutate().request(host).build();
            return chain.filter(build);

            //////////


        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
    }

}
